package com.yanfan.maintain.service.impl;

import cn.hutool.core.util.StrUtil;
import com.yanfan.common.core.domain.entity.SysDictData;
import com.yanfan.common.core.domain.entity.SysUser;
import com.yanfan.common.core.domain.model.LoginUser;
import com.yanfan.common.exception.base.BaseException;
import com.yanfan.common.utils.DateUtils;
import com.yanfan.common.utils.SecurityUtils;
import com.yanfan.common.utils.StringUtils;
import com.yanfan.energy.domain.*;
import com.yanfan.energy.domain.enums.DeviceManageEnums;
import com.yanfan.maintain.mapper.ImageUrlDao;
import com.yanfan.maintain.mapper.InventoryLogDao;
import com.yanfan.energy.mapper.VulnerableItemsDao;
import com.yanfan.energy.domain.SpareParts;
import com.yanfan.maintain.domain.SparePartsDevice;
import com.yanfan.maintain.domain.SparePartsDeviceExample;
import com.yanfan.maintain.mapper.SparePartsDao;
import com.yanfan.maintain.mapper.SparePartsDeviceMapper;
import com.yanfan.maintain.service.SparePartsService;
import com.yanfan.system.mapper.SysDictDataMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;


/**
 * 备品备件表(SpareParts)表服务实现类
 *
 * @author makejava
 * @since 2023-03-14 12:12:25
 */
@Service("sparePartsService")
@Transactional(rollbackFor = Exception.class)
public class SparePartsServiceImpl implements SparePartsService {
    @Autowired
    private SparePartsDao sparePartsDao;
    @Autowired
    private InventoryLogDao inventoryLogDao;
    @Autowired
    private VulnerableItemsDao vulnerableItemsDao;
    @Autowired
    private SysDictDataMapper dictDataMapper;
    @Autowired
    private SparePartsDeviceMapper sparePartsDeviceMapper;
    @Autowired
    private ImageUrlDao imageUrlDao;

    /**
     * 通过ID查询单条数据
     *
     * @param id 主键
     * @return 实例对象
     */
    @Override
    public SpareParts queryById(Long id) {
        return this.sparePartsDao.queryById(id);
    }

    /**
     * 分页查询
     *
     * @param spareParts 筛选条件
     * @return 查询结果
     */
    @Override
    public List<SpareParts> queryByPage(SpareParts spareParts) {
        SysUser user = SecurityUtils.getLoginUser().getUser();
        if (!user.isAdmin()) {
            spareParts.setUserId(user.getUserId());
        }
        return this.sparePartsDao.queryAll(spareParts);
    }

    /**
     * 新增数据
     *
     * @param spareParts 实例对象
     * @return 实例对象
     */
    @Override
    public SpareParts insert(SpareParts spareParts) {
        spareParts.setPartNumber(generateTaskNo());
        spareParts.setCreateBy(String.valueOf(SecurityUtils.getUserId()));
        spareParts.setCreateTime(DateUtils.getNowDate());
        spareParts.setUpdateBy(String.valueOf(SecurityUtils.getUserId()));
        spareParts.setUpdateTime(DateUtils.getNowDate());
        this.sparePartsDao.insert(spareParts);
        if (!CollectionUtils.isEmpty(spareParts.getDeviceList())) {
            batchInsertAssoDevice(spareParts.getDeviceList().stream().map(di -> {
                SparePartsDevice spd = new SparePartsDevice();
                spd.setDeviceId(di.getDeviceId());
                spd.setDeviceName(di.getDeviceName());
                spd.setPartId(spareParts.getId());
                return spd;
            }).collect(Collectors.toList()));
        }
        updatePartImgs(spareParts);
        return spareParts;
    }

    /**
     * 修改数据
     *
     * @param spareParts 实例对象
     * @return 实例对象
     */
    @Override
    public SpareParts update(SpareParts spareParts) {
        spareParts.setUpdateBy(String.valueOf(SecurityUtils.getUserId()));
        spareParts.setUpdateTime(DateUtils.getNowDate());
        this.sparePartsDao.update(spareParts);
        return this.queryById(spareParts.getId());
    }

    /**
     * 通过主键删除数据
     *
     * @param id 主键
     * @return 是否成功
     */
    @Override
    public boolean deleteById(Long id) {
        return this.sparePartsDao.deleteById(id) > 0;
    }

    @Override
    public List<DeviceVo> deviceList() {
        return sparePartsDao.deviceList();
    }

    @Override
    public String inOutOrderNumber(SparePartOperateVo vo) {
        OrderSequence orderSequence = new OrderSequence();
        sparePartsDao.sequenceNext(orderSequence);
        String seq = String.format("%07d", orderSequence.getId());
        if (vo.getInOrOutType().equals(1)) {
            return "in-" + seq;
        } else {
            return "out-" + seq;
        }
    }

    /**
     * 出入库接口
     *
     * @param inventoryLog
     * @return
     */
    @Override
    public int inOut(InventoryLog inventoryLog) {
        inOutParamVerify(inventoryLog);
        return inventoryLogDao.insert(inventoryLog);
    }

    @Override
    public List<InventoryLog> queryItemLog(InventoryLog inventoryLog) {
        return inventoryLogDao.queryAll(inventoryLog);
    }

    @Override
    public List<InventoryLog> queryPartsLog(InventoryLog inventoryLog) {
        return inventoryLogDao.queryPartsLog(inventoryLog);
    }

    @Override
    public List<BaseOrderEntity> owningSystem() {
        SysDictData dictData = new SysDictData();
        dictData.setDictType("system_name");
        List<SysDictData> sysDictData = dictDataMapper.selectDictDataList(dictData);
        List<BaseOrderEntity> arrList = new ArrayList<>();
        if (CollectionUtils.isEmpty(sysDictData)) {
            return arrList;
        }
        for (SysDictData sysDictDatum : sysDictData) {
            BaseOrderEntity base1 = new BaseOrderEntity();
            base1.setId(Long.valueOf(sysDictDatum.getDictValue()));
            base1.setName(sysDictDatum.getDictLabel());
            arrList.add(base1);
        }
        return arrList;
    }

    private void inOutParamVerify(InventoryLog inventoryLog) {
        Integer itemType = inventoryLog.getItemType();
        if (itemType == null || !DeviceManageEnums.ItemType.thisTypeisExist(itemType)) {
            throw new BaseException("itemType 不能为空，   1表示备品备件，2表示易损件");
        }
        Integer inOutType = inventoryLog.getType();
        if (inOutType == null || !DeviceManageEnums.InOutType.thisTypeisExist(inOutType)) {
            throw new BaseException("type 不能为空，  1表示入库，2表示出库");
        }
        Date now = new Date();
        Long num = null; // 剩余库存
        // 验证 出入库数量是否对的上
        if (DeviceManageEnums.ItemType.SPARE_PARTS.getCode().equals(itemType)) { // 备品备件
            num = sparePartsModify(inventoryLog, inOutType, now);
        } else {
            num = spareItemModify(inventoryLog, inOutType, now);  // 表示易损件
        }
        inventoryLog.setQuantity(inventoryLog.getQuantity()); // 库存
        LoginUser loginUser = SecurityUtils.getLoginUser();
        inventoryLog.setCreateTime(now); // 出入库时间
        inventoryLog.setOperatorId(loginUser.getUserId()); // 操作人
        inventoryLog.setOperatorName(loginUser.getUser().getNickName()); // 操作人名称
        inventoryLog.setRemainingStock(num);
    }

    /**
     * 表示易损件
     *
     * @param inventoryLog
     * @param inOutType
     * @param now
     * @return
     */
    private Long spareItemModify(InventoryLog inventoryLog, Integer inOutType, Date now) {
        VulnerableItems vulnerableItems = vulnerableItemsDao.queryById(inventoryLog.getItemId());
        if (vulnerableItems == null) {
            throw new BaseException("备品备件 不存在");
        }
        Long stockQuantity = vulnerableItems.getStockQuantity(); // 存储量
        Long num;
        if (DeviceManageEnums.InOutType.OUT.getCode().equals(inOutType)) {
            num = stockQuantity - inventoryLog.getQuantity();
            if (num < 0) {
                throw new BaseException("库存量不足");
            }
            vulnerableItems.setLastOutTime(now);

        } else {
            num = stockQuantity + inventoryLog.getQuantity();
            vulnerableItems.setLastInTime(now);
        }
        vulnerableItems.setStockQuantity(num);
        // 更新备品备件
        vulnerableItemsDao.update(vulnerableItems);
        return num;
    }

    /**
     * 表示备品备件
     *
     * @param inventoryLog
     * @param inOutType
     * @param now
     * @return
     */
    private Long sparePartsModify(InventoryLog inventoryLog, Integer inOutType, Date now) {
        SpareParts spareParts = sparePartsDao.queryById(inventoryLog.getItemId());
        if (spareParts == null) {
            throw new BaseException("易损件 不存在");
        }
        // 存储量
        Long stockQuantity = spareParts.getStockQuantity();
        Long num;
        if (DeviceManageEnums.InOutType.OUT.getCode().equals(inOutType)) {
            num = stockQuantity - inventoryLog.getQuantity();
            if (num < 0) {
                throw new BaseException("库存量不足");
            }
            spareParts.setLastOutTime(now);
        } else {
            num = stockQuantity + inventoryLog.getQuantity();
            spareParts.setLastInTime(now);
        }
        spareParts.setStockQuantity(num);
        // 更新备品备件
        sparePartsDao.update(spareParts);
        return num;
    }

    @Override
    public List<SparePartsDevice> selectAssoDeviceList(SparePartsDevice partsDevice) {
        SparePartsDeviceExample example = new SparePartsDeviceExample();
        SparePartsDeviceExample.Criteria criteria = example.createCriteria();
        if (Objects.nonNull(partsDevice.getDeviceId())) {
            criteria.andDeviceIdEqualTo(partsDevice.getDeviceId());
        }
        if (Objects.nonNull(partsDevice.getPartId())) {
            criteria.andPartIdEqualTo(partsDevice.getPartId());
        }
        if (StringUtils.isNotEmpty(partsDevice.getDevicePlace())) {
            criteria.andDevicePlaceLike("%" + partsDevice.getDevicePlace() + "%");
        }
        if (StringUtils.isNotEmpty(partsDevice.getDeviceName())) {
            criteria.andDeviceNameLike("%" + partsDevice.getDeviceName() + "%");
        }
        return sparePartsDeviceMapper.selectByExample(example);
    }

    @Override
    public int batchInsertAssoDevice(List<SparePartsDevice> partsDeviceList) {
        return sparePartsDeviceMapper.batchInsertAssoDevice(partsDeviceList);
    }

    @Override
    public List<ImageUrl> selectPartImgs(SpareParts parts) {
        ImageUrl imageUrl = new ImageUrl();
        imageUrl.setType(DeviceManageEnums.ImageType.DEVICE_PARTS.getCode());
        imageUrl.setOrderId(parts.getId());
        imageUrl.setBusType(1);
        return imageUrlDao.queryAll(imageUrl);
    }

    @Override
    public int updatePartImgs(SpareParts parts) {
        ImageUrl imgs = new ImageUrl();
        imgs.setOrderId(parts.getId());
        imgs.setType(DeviceManageEnums.ImageType.DEVICE_PARTS.getCode());
        imgs.setBusType(1);

        if (Objects.nonNull(parts.getImageUrlList())) {
            int di = imageUrlDao.deleteByOrderIdType(imgs);
            if (!CollectionUtils.isEmpty(parts.getImageUrlList())) {
                for (ImageUrl imageUrl : parts.getImageUrlList()) {
                    if (!StrUtil.isEmpty(imageUrl.getImgUrl())) {
                        imageUrl.setOrderId(parts.getId());
                        imageUrl.setType(DeviceManageEnums.ImageType.DEVICE_PARTS.getCode());
                        imageUrl.setBusType(1);
                    }
                }
                return imageUrlDao.insertBatch(parts.getImageUrlList());
            } else {
                return di;
            }
        }
        return 0;
    }

    @Override
    public int cancelAssoDevice(Integer assoId) {
        return sparePartsDeviceMapper.deleteByPrimaryKey(assoId);
    }


    /**
     * 自动生成任务号
     *
     * @return
     */
    public String generateTaskNo() {
        OrderSequence orderSequence = new OrderSequence();
        sparePartsDao.sequenceNext(orderSequence);
        String seq = String.format("%07d", orderSequence.getId());
        return "BJ-" + seq;
    }

    @Override
    public int giveBack(InventoryLog inventoryLog) {
        boolean is = inventoryLogDao.isGiveBack(inventoryLog);
        if (!is) {
            return 0;
        }
        inOutParamVerify(inventoryLog);
        return inventoryLogDao.insert(inventoryLog);
    }
}
